$(GTK_DEP_LIBS)
gtk_reftest_SOURCES = \
+ reftest-module.c \
+ reftest-module.h \
gtk-reftest.c
clean-local:
#include "config.h"
+#include "reftest-module.h"
+
#include <string.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
return output_dir;
}
+static void
+get_components_of_test_file (const char *test_file,
+ char **directory,
+ char **basename)
+{
+ if (directory)
+ {
+ *directory = g_path_get_dirname (test_file);
+ }
+
+ if (basename)
+ {
+ char *base = g_path_get_basename (test_file);
+
+ if (g_str_has_suffix (base, ".ui"))
+ base[strlen (base) - strlen (".ui")] = '\0';
+
+ *basename = base;
+ }
+}
+
static char *
get_output_file (const char *test_file,
const char *extension)
const char *output_dir = get_output_dir ();
char *result, *base;
- base = g_path_get_basename (test_file);
- if (g_str_has_suffix (base, ".ui"))
- base[strlen (base) - strlen (".ui")] = '\0';
+ get_components_of_test_file (test_file, NULL, &base);
result = g_strconcat (output_dir, G_DIR_SEPARATOR_S, base, extension, NULL);
g_free (base);
gboolean must_exist)
{
GString *file = g_string_new (NULL);
+ char *dir, *base;
- if (g_str_has_suffix (test_file, ".ui"))
- g_string_append_len (file, test_file, strlen (test_file) - strlen (".ui"));
- else
- g_string_append (file, test_file);
-
+ get_components_of_test_file (test_file, &dir, &base);
+
+ file = g_string_new (dir);
+ g_string_append (file, G_DIR_SEPARATOR_S);
+ g_string_append (file, base);
g_string_append (file, extension);
+ g_free (dir);
+ g_free (base);
+
if (must_exist &&
!g_file_test (file->str, G_FILE_TEST_EXISTS))
{
return surface;
}
+static void
+connect_signals (GtkBuilder *builder,
+ GObject *object,
+ const gchar *signal_name,
+ const gchar *handler_name,
+ GObject *connect_object,
+ GConnectFlags flags,
+ gpointer directory)
+{
+ ReftestModule *module;
+ GCallback func;
+ GClosure *closure;
+ char **split;
+
+ split = g_strsplit (handler_name, ":", -1);
+
+ switch (g_strv_length (split))
+ {
+ case 1:
+ func = gtk_builder_lookup_callback_symbol (builder, split[0]);
+
+ if (func)
+ {
+ module = NULL;
+ }
+ else
+ {
+ module = reftest_module_new_self ();
+ if (module == NULL)
+ {
+ g_error ("glib compiled without module support.");
+ return;
+ }
+ func = reftest_module_lookup (module, split[0]);
+ if (!func)
+ {
+ g_error ("failed to lookup handler for name '%s' when connecting signals", split[0]);
+ return;
+ }
+ }
+ break;
+ case 2:
+ module = reftest_module_new (directory, split[0]);
+ if (module == NULL)
+ {
+ g_error ("Could not load module '%s' when looking up '%s'", split[0], handler_name);
+ return;
+ }
+ func = reftest_module_lookup (module, split[1]);
+ if (!func)
+ {
+ g_error ("failed to lookup handler for name '%s' in module '%s'", split[1], split[0]);
+ return;
+ }
+ break;
+ default:
+ g_error ("Could not connect signal handler named '%s'", handler_name);
+ return;
+ }
+
+ g_strfreev (split);
+
+ if (connect_object)
+ {
+ if (flags & G_CONNECT_SWAPPED)
+ closure = g_cclosure_new_object_swap (func, connect_object);
+ else
+ closure = g_cclosure_new_object (func, connect_object);
+ }
+ else
+ {
+ if (flags & G_CONNECT_SWAPPED)
+ closure = g_cclosure_new_swap (func, NULL, NULL);
+ else
+ closure = g_cclosure_new (func, NULL, NULL);
+ }
+
+ if (module)
+ g_closure_add_finalize_notifier (closure, module, (GClosureNotify) reftest_module_unref);
+
+ g_signal_connect_closure (object, signal_name, closure, flags & G_CONNECT_AFTER ? TRUE : FALSE);
+}
+
static cairo_surface_t *
snapshot_ui_file (const char *ui_file)
{
GtkWidget *window;
GtkBuilder *builder;
GError *error = NULL;
+ char *directory;
+
+ get_components_of_test_file (ui_file, &directory, NULL);
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, ui_file, &error);
g_assert_no_error (error);
- gtk_builder_connect_signals (builder, NULL);
+ gtk_builder_connect_signals_full (builder, connect_signals, directory);
window = builder_get_toplevel (builder);
g_object_unref (builder);
g_assert (window);
static cairo_surface_t *
buffer_diff_core (const guchar *buf_a,
int stride_a,
- const guchar *buf_b,
+ const guchar *buf_b,
int stride_b,
- int width,
- int height)
+ int width,
+ int height)
{
int x, y;
guchar *buf_diff = NULL;
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "reftest-module.h"
+
+struct _ReftestModule {
+ int refcount;
+ char *filename;
+ GModule *module;
+};
+
+
+static GHashTable *all_modules = NULL;
+
+static ReftestModule *
+reftest_module_find_existing (const char *filename)
+{
+ if (all_modules == NULL)
+ return NULL;
+
+ return g_hash_table_lookup (all_modules, filename ? filename : "");
+}
+
+static ReftestModule *
+reftest_module_new_take (GModule *module,
+ char *filename)
+{
+ ReftestModule *result;
+
+ g_return_val_if_fail (module != NULL, NULL);
+
+ result = g_slice_new0 (ReftestModule);
+
+ result->refcount = 1;
+ result->filename = filename;
+ result->module = module;
+
+ if (all_modules == NULL)
+ all_modules = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (all_modules, filename ? filename : "", result);
+
+ return result;
+}
+
+ReftestModule *
+reftest_module_new_self (void)
+{
+ ReftestModule *result;
+ GModule *module;
+
+ result = reftest_module_find_existing (NULL);
+ if (result)
+ return reftest_module_ref (result);
+
+ module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+ if (module == NULL)
+ return NULL;
+
+ return reftest_module_new_take (module, NULL);
+}
+
+ReftestModule *
+reftest_module_new (const char *directory,
+ const char *module_name)
+{
+ ReftestModule *result;
+ char *full_path;
+ GModule *module;
+
+ g_return_val_if_fail (module_name != NULL, NULL);
+
+ full_path = g_module_build_path (directory, module_name);
+
+ result = reftest_module_find_existing (full_path);
+ if (result)
+ {
+ g_free (full_path);
+ return reftest_module_ref (result);
+ }
+
+ module = g_module_open (full_path, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
+ if (module == NULL)
+ {
+ /* libtool hack */
+ char *libtool_dir = g_build_path (directory, ".libs", NULL);
+
+ g_free (full_path);
+ full_path = g_module_build_path (libtool_dir, module_name);
+
+ result = reftest_module_find_existing (full_path);
+ if (result)
+ {
+ g_free (full_path);
+ return reftest_module_ref (result);
+ }
+
+ module = g_module_open (full_path, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
+ if (module == NULL)
+ {
+ g_free (full_path);
+ return NULL;
+ }
+ }
+
+ return reftest_module_new_take (module, full_path);
+}
+
+ReftestModule *
+reftest_module_ref (ReftestModule *module)
+{
+ g_return_val_if_fail (module != NULL, NULL);
+
+ module->refcount++;
+
+ return module;
+}
+
+void
+reftest_module_unref (ReftestModule *module)
+{
+ g_return_if_fail (module != NULL);
+
+ module->refcount--;
+ if (module->refcount > 0)
+ return;
+
+ if (!g_module_close (module->module))
+ {
+ g_assert_not_reached ();
+ }
+
+ if (!g_hash_table_remove (all_modules, module->filename ? module->filename : ""))
+ {
+ g_assert_not_reached ();
+ }
+
+ g_free (module->filename);
+ g_slice_free (ReftestModule, module);
+}
+
+GCallback
+reftest_module_lookup (ReftestModule *module,
+ const char *function_name)
+{
+ gpointer result;
+
+ g_return_val_if_fail (module != NULL, NULL);
+ g_return_val_if_fail (function_name != NULL, NULL);
+
+ if (!g_module_symbol (module->module, function_name, &result))
+ return NULL;
+
+ return result;
+}
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __REFTEST_MODULE_H__
+#define __REFTEST_MODULE_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ReftestModule ReftestModule;
+
+ReftestModule * reftest_module_new (const char *directory,
+ const char *module_name);
+ReftestModule * reftest_module_new_self (void);
+
+ReftestModule * reftest_module_ref (ReftestModule *module);
+void reftest_module_unref (ReftestModule *module);
+
+GCallback reftest_module_lookup (ReftestModule *module,
+ const char *function_name);
+
+G_END_DECLS
+
+#endif /* __REFTEST_MODULE_H__ */